{
  "nbformat": 4,
  "nbformat_minor": 0,
  "metadata": {
    "colab": {
      "name": "k交叉验证main",
      "provenance": [],
      "collapsed_sections": [],
      "toc_visible": true
    },
    "kernelspec": {
      "name": "python3",
      "display_name": "Python 3"
    }
  },
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "9KsuyQbZf-RS",
        "colab_type": "text"
      },
      "source": [
        "# 连接云盘"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "uuYLnAPsf46g",
        "colab_type": "code",
        "outputId": "cd5fe3d6-3e75-4bbf-ad83-807535d6dcc0",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 121
        }
      },
      "source": [
        "from google.colab import drive\n",
        "drive.mount('/content/drive/')"
      ],
      "execution_count": 0,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "Go to this URL in a browser: https://accounts.google.com/o/oauth2/auth?client_id=947318989803-6bn6qk8qdgf4n4g3pfee6491hc0brc4i.apps.googleusercontent.com&redirect_uri=urn%3aietf%3awg%3aoauth%3a2.0%3aoob&response_type=code&scope=email%20https%3a%2f%2fwww.googleapis.com%2fauth%2fdocs.test%20https%3a%2f%2fwww.googleapis.com%2fauth%2fdrive%20https%3a%2f%2fwww.googleapis.com%2fauth%2fdrive.photos.readonly%20https%3a%2f%2fwww.googleapis.com%2fauth%2fpeopleapi.readonly\n",
            "\n",
            "Enter your authorization code:\n",
            "··········\n",
            "Mounted at /content/drive/\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "hg5EQ6qugIV_",
        "colab_type": "text"
      },
      "source": [
        "# import"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "SIK1fI4tgMT3",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "import torch\n",
        "from torch.autograd import Variable\n",
        "from torch.utils.data import Dataset, DataLoader\n",
        "import torch.nn as nn\n",
        "import torch.nn.functional as F\n",
        "import torch.optim as optim\n",
        "from torch.optim.lr_scheduler import StepLR\n",
        "from torchvision import datasets, transforms, models\n",
        "from torchvision.datasets import ImageFolder\n",
        "import torchvision.models as models\n",
        "import numpy as np\n",
        "import cv2\n",
        "from PIL import Image\n",
        "import os\n",
        "from matplotlib import pyplot as plt\n"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "Plc3d6p0gOkX",
        "colab_type": "text"
      },
      "source": [
        "# 全局变量"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "VsL660UwgL3n",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "\n",
        "batch_size = 100\n",
        "test_batch_size = 10\n",
        "mini_batch_size = 10\n",
        "epochs = 5\n",
        "lr = 0.01\n",
        "gamma = 0.9\n",
        "no_cuda = True\n",
        "seed = 1\n",
        "log_interval = 10\n",
        "save_model = True\n",
        "\n",
        "base_dirs = ['pinghe/', 'qixu/', 'qiyu/', 'shire/', 'tanshi/', 'xueyu/', 'yangxu/', 'yinxu/']\n",
        "root = \"./drive/My Drive/data/dataset6/\"\n",
        "\n",
        "loss_fun = nn.CrossEntropyLoss()  #交叉熵"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "ERdcfznYgVKX",
        "colab_type": "text"
      },
      "source": [
        "# MyDataset类"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "1vdh-KARgVkl",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "\n",
        "def default_loader(path):\n",
        "    normalize = transforms.Normalize(mean=[0.485, 0.456, 0.406],std=[0.229, 0.224, 0.225])\n",
        "    preprocess = transforms.Compose([transforms.ToTensor(),normalize])\n",
        "\n",
        "    img_pil =  Image.open(path)    \n",
        "    img_tensor = preprocess(img_pil)\n",
        "    return img_tensor\n",
        "\n",
        "\n",
        "class MyDataset(Dataset):\n",
        "    def __init__(self, root, base_dirs,loader=default_loader):\n",
        "        self.image_label_list, self.image_path_list  = self.read_file(root,base_dirs)\n",
        "        self.root = root\n",
        "        self.base_dirs=base_dirs\n",
        "        self.len = len(self.image_label_list)\n",
        "        self.loader = loader\n",
        "  \n",
        "    def __getitem__(self, i):\n",
        "        index = i\n",
        "        label = self.image_label_list[index]\n",
        "        path = self.image_path_list[index]        \n",
        "        img = self.loader(path)        \n",
        "        return img, label\n",
        "\n",
        "    def __len__(self):\n",
        "        data_len = len(self.image_label_list)\n",
        "        return data_len\n",
        "\n",
        "    #返回标签列表、目录列表\n",
        "    def read_file(self,root,base_dirs):\n",
        "        image_label_list = []\n",
        "        image_path_list = []\n",
        "\n",
        "        for i in range(len(base_dirs)):\n",
        "            dir=root+base_dirs[i]\n",
        "            listImages = [dir+ Image for Image in (os.listdir(dir))]\n",
        "            for file in listImages:\n",
        "                image_label_list.append(i)\n",
        "                image_path_list.append(file)\n",
        "\n",
        "        return image_label_list,image_path_list\n",
        "\n",
        "\n"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "8EZRNW1ugeAY",
        "colab_type": "text"
      },
      "source": [
        "# 非k折验证"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "76lpYvsXgvrI",
        "colab_type": "text"
      },
      "source": [
        "## train"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "H50lFPxVgpQc",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "\n",
        "\n",
        "def train(model, device, train_loader, optimizer, epoch):\n",
        "    model.train()\n",
        "    tot_loss=0.0\n",
        "    for batch_idx, (data, target) in enumerate(train_loader):\n",
        "        data, target = data.to(device), target.to(device)\n",
        "        optimizer.zero_grad()\n",
        "\n",
        "        # forward backward\n",
        "        output = model(data)\n",
        "        loss = loss_fun(output, target)\n",
        "        loss.backward()\n",
        "        optimizer.step()\n",
        "        tot_loss += loss.item()\n",
        "        \n",
        "        \n",
        "        print('Train Epoch: {} [{}/{} ({:.0f}%)]\\tLoss: {:.6f}'.format(\n",
        "                epoch, batch_idx * len(data), len(train_loader.dataset),\n",
        "                       100. * batch_idx / len(train_loader), loss.item()))\n",
        "        \n",
        "        #print(tot_loss/len(train_loader))\n",
        "        #print('\\ntrain set: Average loss: {:.4f}'.format(tot_loss/len(train_loader)))\n",
        "\n",
        "\n",
        "\n"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "cf0MtadHgx14",
        "colab_type": "text"
      },
      "source": [
        "## test"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "1garLQ5pg1R4",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "\n",
        "def test( model, device, test_loader):\n",
        "    model.eval()\n",
        "    test_loss = 0.0\n",
        "    correct = 0\n",
        "    with torch.no_grad():\n",
        "        for data, target in test_loader:\n",
        "            data, target = data.to(device), target.to(device)\n",
        "            output = model(data)\n",
        "            test_loss+=loss_fun(output, target)\n",
        "            pred = output.argmax(dim=1, keepdim=True)  # get the index of the max log-probability\n",
        "            correct += pred.eq(target.view_as(pred)).sum().item()\n",
        "\n",
        "    test_loss /= len(test_loader.dataset)\n",
        "\n",
        "    print('\\nTest set: Average loss: {:.4f}, Accuracy: {}/{} ({:.0f}%)\\n'.format(\n",
        "        test_loss, correct, len(test_loader.dataset),\n",
        "        100. * correct / len(test_loader.dataset)))\n",
        "    \n"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "mOQoUhdSg_H_",
        "colab_type": "text"
      },
      "source": [
        "## main"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "6wZ3fzgOhA0H",
        "colab_type": "code",
        "outputId": "907b4125-c2e7-4022-8d09-514342eb3890",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 316
        }
      },
      "source": [
        "\n",
        "\n",
        "def main():\n",
        "    use_cuda = not no_cuda and torch.cuda.is_available()\n",
        "    device = torch.device(\"cuda\" if use_cuda else \"cpu\")\n",
        "    torch.manual_seed(seed)    \n",
        "\n",
        "    kwargs = {'num_workers': 1, 'pin_memory': True} if use_cuda else {}\n",
        "    \n",
        "\n",
        "    train_data=MyDataset(root, base_dirs)\n",
        "    test_data=MyDataset(root, base_dirs)\n",
        "\n",
        "    train_loader = torch.utils.data.DataLoader(train_data,\n",
        "                            batch_size=batch_size, shuffle=True, **kwargs)\n",
        "    test_loader = torch.utils.data.DataLoader(test_data,\n",
        "                            batch_size=test_batch_size, shuffle=True, **kwargs)\n",
        "    '''\n",
        "    model =Net().to(device)    \n",
        "    '''\n",
        "    \n",
        "    model=models.resnet18(pretrained=True)\n",
        "    model.fc = nn.Linear(512,8)\n",
        "    model=model.to(device)\n",
        "    \n",
        "    #交叉熵\n",
        "    loss_fun = nn.CrossEntropyLoss()\n",
        "    #momentumSGD\n",
        "    optimizer = optim.SGD(model.parameters(), lr=lr, momentum=0.9, weight_decay=0.005)\n",
        "\n",
        "    scheduler = StepLR(optimizer, step_size=1, gamma=gamma)\n",
        "    for epoch in range(1, epochs + 1):\n",
        "        train(model, device, train_loader, optimizer, epoch)\n",
        "        test(model, device, test_loader)\n",
        "        scheduler.step()\n",
        "\n",
        "    if save_model:\n",
        "        torch.save(model.state_dict(), \"res01.pt\")\n",
        "\n",
        "\n",
        "\n",
        "main()"
      ],
      "execution_count": 0,
      "outputs": [
        {
          "output_type": "error",
          "ename": "NameError",
          "evalue": "ignored",
          "traceback": [
            "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
            "\u001b[0;31mNameError\u001b[0m                                 Traceback (most recent call last)",
            "\u001b[0;32m<ipython-input-7-98e89b21c79d>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[1;32m     36\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     37\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 38\u001b[0;31m \u001b[0mmain\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
            "\u001b[0;32m<ipython-input-7-98e89b21c79d>\u001b[0m in \u001b[0;36mmain\u001b[0;34m()\u001b[0m\n\u001b[1;32m      8\u001b[0m     \u001b[0mkwargs\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m{\u001b[0m\u001b[0;34m'num_workers'\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0;36m1\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m'pin_memory'\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0;32mTrue\u001b[0m\u001b[0;34m}\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0muse_cuda\u001b[0m \u001b[0;32melse\u001b[0m \u001b[0;34m{\u001b[0m\u001b[0;34m}\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m      9\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 10\u001b[0;31m     train_loader = torch.utils.data.DataLoader(train_data,\n\u001b[0m\u001b[1;32m     11\u001b[0m                             batch_size=batch_size, shuffle=True, **kwargs)\n\u001b[1;32m     12\u001b[0m     test_loader = torch.utils.data.DataLoader(test_data,\n",
            "\u001b[0;31mNameError\u001b[0m: name 'train_data' is not defined"
          ]
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "kYuneBLpgp_Y",
        "colab_type": "text"
      },
      "source": [
        "# k折交叉验证"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "vfAfufbihwxY",
        "colab_type": "text"
      },
      "source": [
        "## get_k_fold_data"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "n4uxBZIAhwG4",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "k = 10\n",
        "\n",
        "def get_k_fold_data(k, i, X, y):\n",
        "  # 返回第i折交叉验证时所需要的训练和验证数据\n",
        "  assert k > 1\n",
        "  fold_size = X.shape[0]\n",
        "  X_train, y_train = None, None\n",
        "  for j in range(k):\n",
        "    idx = slice(j * fold_size, (j + 1) * fold_size)\n",
        "    X_part, y_part = X[idx, :], y[idx]\n",
        "    \n",
        "    if j == i:\n",
        "      X_valid, y_valid = X_part, y_part\n",
        "    elif X_train is None:\n",
        "      X_train, y_train = X_part, y_part\n",
        "    else:\n",
        "      X_train = torch.cat((X_train, X_part), dim=0)\n",
        "      y_train = torch.cat((y_train, y_part), dim=0)\n",
        "  return X_train, y_train, X_valid, y_valid"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "wiPAP4I1hO47",
        "colab_type": "text"
      },
      "source": [
        "## k_fold"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "8YxHNSlogqQ4",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "#训练k次并返回训练和验证的平均误差\n",
        "\n",
        "def k_fold(k, X_train, y_train, num_epochs,learning_rate, weight_decay, batch_size):\n",
        "  train_l_sum, valid_l_sum = 0, 0\n",
        "  train_acc_sum ,valid_acc_sum = 0,0\n",
        "\n",
        "  for i in range(k):\n",
        "    data = get_k_fold_data(k, i, X_train, y_train)\n",
        "    net = Net()\n",
        "\n",
        "    train_ls, valid_ls = train(net, *data, num_epochs,learning_rate,weight_decay, batch_size)\n",
        "    train_l_sum += train_ls[-1]\n",
        "    valid_l_sum += valid_ls[-1]\n",
        "\n",
        "    if i == 0:\n",
        "      d2l.semilogy(range(1, num_epochs + 1), train_ls,'epochs', 'rmse',range(1, num_epochs + 1), valid_ls,['train', 'valid'])\n",
        "    print('fold %d, train rmse %f, valid rmse %f' % (i,train_ls[-1], valid_ls[-1]))\n",
        "    \n",
        "  return train_l_sum / k, valid_l_sum / k"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "HAPW06e4HTIr",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "def semilogy(x_vals, y_vals, x_label, y_label, x2_vals=None,y2_vals=None,\n",
        "  legend=None, figsize=(3.5, 2.5)):\n",
        "  d2l.set_figsize(figsize)\n",
        "  d2l.plt.xlabel(x_label)\n",
        "  d2l.plt.ylabel(y_label)\n",
        "  d2l.plt.semilogy(x_vals, y_vals)\n",
        "  if x2_vals and y2_vals:\n",
        "    d2l.plt.semilogy(x2_vals, y2_vals, linestyle=':')\n",
        "    d2l.plt.legend(legend)"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "rDSjHVb3hbYH",
        "colab_type": "text"
      },
      "source": [
        "## train"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "B94u89_WhdgP",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "def train(net, train_features, train_labels, test_features, test_labels, num_epochs, learning_rate,weight_decay, batch_size):\n",
        "    train_ls, test_ls = [], [] ##存储train_loss,test_loss\n",
        "    dataset = TraindataSet(train_features, train_labels) \n",
        "    train_iter = DataLoader(dataset, batch_size, shuffle=True) \n",
        "    ### 将数据封装成 Dataloder 对应步骤（2）\n",
        "    \n",
        "    #这里使用了Adam优化算法\n",
        "    optimizer = torch.optim.Adam(params=net.parameters(), lr= learning_rate, weight_decay=weight_decay)\n",
        "    \n",
        "    for epoch in range(num_epochs):\n",
        "        for X, y in train_iter:  ###分批训练 \n",
        "            output  = net(X)\n",
        "            loss = loss_func(output,y)\n",
        "            optimizer.zero_grad()\n",
        "            loss.backward()\n",
        "            optimizer.step()\n",
        "        ### 得到每个epoch的 loss 和 accuracy \n",
        "        train_ls.append(log_rmse(0,net, train_features, train_labels)) \n",
        "        if test_labels is not None:\n",
        "            test_ls.append(log_rmse(1,net, test_features, test_labels))\n",
        "    #print(train_ls,test_ls)\n",
        "    return train_ls, test_ls"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "JMIICg2CFoAt",
        "colab_type": "text"
      },
      "source": [
        "## log_rmse"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "P9asBLziFqck",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "\n",
        "def log_rmse(flag,net,x,y):\n",
        "    if flag == 1: ### valid 数据集\n",
        "        net.eval()\n",
        "    output = net(x)\n",
        "    result = torch.max(output,1)[1].view(y.size())\n",
        "    corrects = (result.data == y.data).sum().item()\n",
        "    accuracy = corrects*100.0/len(y)  #### 5 是 batch_size\n",
        "    loss = loss_func(output,y)\n",
        "    net.train()\n",
        "    \n",
        "    return (loss.data.item(),accuracy)"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "iSQD26hjFuNh",
        "colab_type": "text"
      },
      "source": [
        "## main"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "aaFmvbd8FwU8",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "k = 10\n",
        " \n",
        "k_fold(10,x,label)"
      ],
      "execution_count": 0,
      "outputs": []
    }
  ]
}